package com.dmy.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dmy.common.exception.ExinException;
import com.dmy.common.exception.UserNameNotFountException;
import com.dmy.common.utils.JsonUtils;
import com.dmy.common.utils.Md5Util;
import com.dmy.common.utils.qr_code.QRCodeConfig;
import com.dmy.common.utils.qr_code.QRCodeHelper;
import com.dmy.mapper.FriendBindMapper;
import com.dmy.mapper.FriendsRequestMapper;
import com.dmy.mapper.UserMapper;
import com.dmy.model.EUser;
import com.dmy.model.FriendsBind;
import com.dmy.model.FriendsRequest;
import com.dmy.service.IUserService;
import com.dmy.vo.helper.FriendListGroupHelper;
import com.dmy.vo.FriendListVo;
import com.dmy.vo.FriendRequestVo;
import com.dmy.vo.helper.GroupType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * create by huahuadelei for 2020/1/4
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,EUser> implements IUserService {

    @Resource(name = "stringRedisTemplate")
    private StringRedisTemplate redisTemplate;
    @Autowired
    private FriendsRequestMapper friendsRequestMapper;
    @Autowired
    private FriendBindMapper friendBindMapper;

    @Override
    public EUser login(EUser eUser) {
        EUser user = baseMapper.selectOne(new QueryWrapper<EUser>().eq("username", eUser.getUsername()));
        if(ObjectUtils.isEmpty(user)){
            throw new UserNameNotFountException();
        }

        if(!user.getPassword().equals(Md5Util.pwdDigest(eUser.getPassword()))){
            throw new ExinException("021","密码错误");
        }
        user.setPassword(null);
        String token =  cacheUserInfo(user);
        user.setToken(token);
        return user ;
    }

    @Override
    public EUser getUserInfo(String token) {
        EUser info = findUserInfo(token);
        return info;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void regist(EUser eUser) {
        // 判断用户名是否存在
        List<EUser> eUserList = baseMapper.selectList(new QueryWrapper<EUser>().eq("username", eUser.getUsername()));
        if(eUserList!=null&&!eUserList.isEmpty()){
            throw new ExinException("1101","用户名已存在");
        }

        eUser.setPassword(Md5Util.pwdDigest(eUser.getPassword()));
        eUser.setCreateTime(new Date());
        eUser.setUpdateTime(new Date());
        baseMapper.insert(eUser);
    }

    @Override
    public byte[] loadQr(String token) {
        String currentUserJson = redisTemplate.boundValueOps("USERSESSION:" + token).get();
        EUser eUser = JsonUtils.jsonToPojo(currentUserJson, EUser.class);

        String userId = eUser.getId();

        QRCodeConfig qrCodeConfig = new QRCodeConfig();
        // 获取用户信息 判断是否存在头像
        EUser user = baseMapper.selectById(userId);
        // 存在头像 生成二维码时需要 把用户头像作为logo
//        if(!ObjectUtils.isEmpty(user.getPhotoDefault())){
//            try {
//                HttpHelper.getInstance(HttpHelper.ImplType.JDK_HTTP).get(user.getPhotoDefault(),bytes->{
//                    ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
//                    qrCodeConfig.setCodeLogoConfig(QRCodeConfig.QRCodeLogoConfig.fromFile(inputStream));
//                });
//            } catch (Exception e) {
//            }
//        }
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            QRCodeHelper.getInstance().generateQrCodeToStream("USER:"+userId,qrCodeConfig,byteArrayOutputStream);
        } catch (Exception e) {
            throw new ExinException("0079","生成二维码失败");
        }
        return byteArrayOutputStream.toByteArray();
    }

    @Override
    public EUser findUserById(String userId) {
        EUser user = baseMapper.selectById(userId);
        user.setPassword(null);
        return user;
    }

    @Override
    @Transactional
    public void addUserRequest(String token, String userId,int type) {
        EUser user = getUserInfo(token);
        String currentUserId = user.getId();

        if(currentUserId.equals(userId)){
            throw new ExinException("0033","自己不允许添加自己为好友");
        }
        List<FriendsBind> friendsBinds = friendBindMapper.selectList(new QueryWrapper<FriendsBind>().eq("user_id", currentUserId).eq("friend_id", userId));
        if(!ObjectUtils.isEmpty(friendsBinds)){
            throw new ExinException("0030","该用户已存在您的好友列表中");
        }

        List<FriendsRequest> friendsRequest = friendsRequestMapper.selectList(new QueryWrapper<FriendsRequest>().eq("sender_id", currentUserId).eq("friend_id", userId));

        if(!ObjectUtils.isEmpty(friendsRequest)){
            throw new ExinException("0031","请勿重复发送添加请求");
        }

        FriendsRequest request = new FriendsRequest();
        request.setFriendId(userId);
        request.setCreateTime(new Date());
        request.setUpdateTime(new Date());
        request.setSenderId(currentUserId);
        request.setRequestSource(type);
        friendsRequestMapper.insert(request);
    }

    @Override
    public List<FriendRequestVo> queryFriendsRequest(String token) {
        EUser user = getUserInfo(token);
        List<FriendsRequest> list = friendsRequestMapper.selectList(new QueryWrapper<FriendsRequest>().eq("friend_id", user.getId()));

        List<FriendRequestVo> requestVoList = list.stream().map(f -> {
            EUser sender = baseMapper.selectById(f.getSenderId());
            FriendRequestVo requestVo = new FriendRequestVo();
            requestVo.setId(f.getId());
            requestVo.setType(f.getRequestSource());
            requestVo.setReqUserId(sender.getId());
            requestVo.setName(sender.getName());
            requestVo.setUserNo(sender.getUsername());
            requestVo.setUserPhoto(sender.getPhotoDefault());
            return requestVo;
        }).collect(Collectors.toList());

        return requestVoList;
    }

    @Override
    @Transactional
    public void acceptRequest(String token, String reqId) {
        EUser user = getUserInfo(token);
        FriendsRequest request = friendsRequestMapper.selectById(reqId);

        Date date = new Date();
        // 维护 发送请求的用户 成为自己的好友
        FriendsBind friendsBind = new FriendsBind();
        friendsBind.setBindType(request.getRequestSource());
        friendsBind.setFriendId(request.getSenderId());
        friendsBind.setUserId(user.getId());
        friendsBind.setCreateTime(date);
        friendsBind.setUpdateTime(date);
        friendBindMapper.insert(friendsBind);

        // 维护 自己 成为发送者的好友
        FriendsBind friendsBind2 = new FriendsBind();
        friendsBind2.setBindType(request.getRequestSource());
        friendsBind2.setFriendId(user.getId());
        friendsBind2.setUserId(request.getSenderId());
        friendsBind2.setCreateTime(date);
        friendsBind2.setUpdateTime(date);
        friendBindMapper.insert(friendsBind2);

        String senderId = request.getSenderId();

        // 成为好友 删除自己发送给对方的申请 和 对方发送给自己的申请
        ArrayList<String> ids = new ArrayList<>();
        ids.add(senderId);
        ids.add(user.getId());
        ids.forEach(id->{
            friendsRequestMapper.delete(new QueryWrapper<FriendsRequest>().eq("friend_id",id));
        });
    }

    @Override
    public Map<String,List<FriendListVo>> getFriends(String token) {
        EUser user = getUserInfo(token);
        List<FriendsBind> friends = friendBindMapper.selectList(new QueryWrapper<FriendsBind>().eq("user_id", user.getId()));

        FriendListGroupHelper groupHelper = new FriendListGroupHelper(GroupType.JAVA8_GROUP);

         friends.stream().map(fb -> {

            FriendListVo friendListVo = new FriendListVo();
            friendListVo.setBindType(fb.getBindType());
            friendListVo.setFriendId(fb.getFriendId());
            friendListVo.setId(fb.getId());
            friendListVo.setUserId(user.getId());

            EUser friUser = baseMapper.selectById(fb.getFriendId());
            friendListVo.setFriendName(friUser.getName());
            friendListVo.setPhoto(friUser.getPhotoDefault());
            friendListVo.setFriendUserName(friUser.getUsername());
            return friendListVo;
        }).forEach(fv->{
             groupHelper.push(fv);
        });

        return groupHelper.groupResult();
    }

    @Override
    public void agnoreReq(String token, String reqId) {
        EUser user = getUserInfo(token);
         friendsRequestMapper.deleteById(reqId);
    }

    /**
     * 缓存用户信息
     * @param user
     */
    private String cacheUserInfo(EUser user) {
        String token = Md5Util.pwdDigest(user.getId()+ UUID.randomUUID().toString()+new Date().getTime());
        redisTemplate.boundValueOps("USERSESSION:"+token).set(JsonUtils.objectToJson(user),7, TimeUnit.DAYS);
        return token;
    }
    /**
     * 查询用户信息
     * @param token
     */
    private EUser findUserInfo(String token) {
        String json = redisTemplate.boundValueOps("USERSESSION:" + token).get();
        if(json != null){
            redisTemplate.boundValueOps("USERSESSION:" + token).expire(7,TimeUnit.DAYS);
            return JsonUtils.jsonToPojo(json,EUser.class);
        }
        return null;
    }
}
